﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using Oxage.Controls.AvalonEditExtensions;

namespace Oxage.Views
{
	public partial class CodeCompletionPopup : Popup
	{
		#region Constructor
		public CodeCompletionPopup()
		{
			InitializeComponent();

			this.KeyDown += (sender, e) =>
			{
				HandleKeyDown(e.Key);
			};
		}
		#endregion

		#region Dependency properties

		#region Items
		public IEnumerable<ICodeCompletionItem> Items
		{
			get { return (IEnumerable<ICodeCompletionItem>)GetValue(ItemsProperty); }
			set { SetValue(ItemsProperty, value); }
		}

		public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(IEnumerable<ICodeCompletionItem>), typeof(CodeCompletionPopup), new PropertyMetadata(ItemsChanged));

		private static void ItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			var control = d as CodeCompletionPopup;
			if (control != null)
			{
				control.CompletionListBox.ItemsSource = null;
				control.CompletionListBox.ItemsSource = e.NewValue as IEnumerable;
				control.CompletionListBox.SelectedIndex = 0;
			}
		}
		#endregion

		#endregion

		#region Public properties
		public ICodeCompletionItem SelectedItem
		{
			get
			{
				if (this.CompletionListBox.SelectedIndex > -1 && this.CompletionListBox.SelectedItem is ICodeCompletionItem)
				{
					return this.CompletionListBox.SelectedItem as ICodeCompletionItem;
				}
				else
				{
					return null;
				}
			}
		}
		#endregion

		#region Public methods
		public void Show()
		{
			base.IsOpen = true;
		}

		public void Hide()
		{
			base.IsOpen = false;
		}
		#endregion

		#region Protected methods
		protected CodeCompletionResult GetResult()
		{
			var result = new CodeCompletionResult();
			result.Item = this.SelectedItem;
			result.Handled = false;
			return result;
		}

		public bool HandleKeyDown(Key key)
		{
			bool handled = false;

			switch (key)
			{
				case Key.Tab:
				case Key.Enter:
					OnCompleted(GetResult());
					Hide();
					handled = true;
					break;

				case Key.Escape:
					Hide();
					handled = true;
					break;

				case Key.Up:
					if (this.CompletionListBox.SelectedIndex > 0)
					{
						this.CompletionListBox.SelectedIndex--;
					}
					handled = true;
					break;

				case Key.Down:
					if (this.CompletionListBox.SelectedIndex < this.Items.Count() - 1)
					{
						this.CompletionListBox.SelectedIndex++;
					}
					handled = true;
					break;

				case Key.PageUp:
					break;

				case Key.PageDown:
					break;
			}

			return handled;
		}
		#endregion

		#region Bubble events
		public event EventHandler<CodeCompletionEventArgs> Completed;
		protected virtual void OnCompleted(CodeCompletionResult result)
		{
			if (Completed != null)
			{
				Completed(this, new CodeCompletionEventArgs() { Result = result });
			}
		}
		#endregion

		#region Static methods
		private static CodeCompletionPopup popup = null; //Last used popup instance
		public static CodeCompletionPopup LastPopup { get { return popup; } }
		public static CodeCompletionPopup ShowPopup(IEnumerable<ICodeCompletionItem> items, Point position, Action<CodeCompletionResult> callback)
		{
			if (popup == null)
			{
				//Initialize for the first time
				popup = new CodeCompletionPopup();
				popup.Completed += (sender, e) =>
				{
					if (callback != null)
					{
						callback(e.Result);
					}
				};
			}

			popup.PlacementRectangle = new Rect(position.X, position.Y, 1, 1);
			popup.Items = items;
			popup.Show();

			return popup;
		}
		#endregion
	}
}
